package com.sychip.fhc.app.drawer.screen


import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.viewModelScope
import com.sychip.fhc.MainApplication
import com.sychip.fhc.app.data.repo.BleDeviceRepo
import com.sychip.fhc.app.data.source.dto.BleDeviceDto
import com.sychip.fhc.base.BaseAppViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.UUID


/**
 * ViewModel for the PullList screen.
 */
@HiltViewModel
class PullListViewModel @Inject constructor(
    app : MainApplication,
    private val bleRepo: BleDeviceRepo
) : BaseAppViewModel(app) {

    sealed interface UiTestState {
        object Null : UiTestState
        object Loading : UiTestState
        data class Success(val data: List<BleDeviceDto>) : UiTestState
        data class Error(val throwable: Throwable? = null) : UiTestState

    }

    private val _testFlow = MutableStateFlow<UiTestState>(UiTestState.Null)
    private val _testData : MutableList<BleDeviceDto>  =  mutableStateListOf<BleDeviceDto>()
    val testFlow: StateFlow<UiTestState> = _testFlow.asStateFlow()

    init{

    }
     fun reloadTestData() {
        Timber.i("    >>>>>>>>>>>>>>>>>>>>>>>>>   reloadTestData  reloadTestData   >>>>>>>>>>>>>>>>>>>>>>>>> ")
        _testData.clear()
        _testFlow.update { UiTestState.Loading }
        loadTestData()
    }

     fun loadTestData() {
         // 还有cancel ensureActive，cancelable等写法比较实用
         bleRepo.getAllBleDevices().map { result ->
             //map不是必须，我们可以在里面进行转换数据，然后 onEach....，如果不需要转换，可以移除map结构
             //UiTestState.Success(result) as UiTestState
             result
         }.onCompletion { cause ->

         }.onEach { result ->
             delay(3000)
             _testData.addAll(result)
             _testFlow.update { UiTestState.Success( data = _testData ) }
         }.catch { error ->
             UiTestState.Error(error)
         }.onStart {
             UiTestState.Loading
         }.launchIn(viewModelScope)
    }

    fun addData() {
        bleRepo.createBleDevice(name="ADD"+_testData.size, mac = UUID.randomUUID().toString()).onEach { result ->
            Timber.i("   addData  222 >>>>>>>>>>>>>>>>>>>>>>>>> %s", result.mac)
            _testData.add(result)
            Timber.i("   addData  33333 >>>>>>>>>>>>>>>>>>>>>>>>> %s", _testData.size)

            _testFlow.update { UiTestState.Success( data = _testData ) }
        }.catch { error ->
            UiTestState.Error(error)
        }.onStart {

        }.launchIn(viewModelScope)
    }

    fun deleteData(index:Int = -1, devId: String) {
        val delItem =  if(index < 0)   _testData.find { it.devId == devId } else _testData[index]
        Timber.i("   addData  111 >>>>>>>>>>>>>>>>>>>>>>>>> %s", index)
        viewModelScope.launch{
            val rlt = bleRepo.deleteBleDevice(devId)
            if(rlt > 0){
                _testData.remove(delItem)
            }
        }
    }
}


